﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Win32;
using ManagedVC1;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.ComponentModel;
using System.Xml.Serialization;

namespace EncoderTester
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private EncoderConfiguration m_Config = new EncoderConfiguration();
        private VC1Encoder m_Encoder;

        public Window1()
        {
            Loaded += new RoutedEventHandler(Window1_Loaded);
            InitializeComponent();
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            if (!String.IsNullOrEmpty(App.StartupSettingsFile))
            {
                LoadSettings(App.StartupSettingsFile);
            }
            else x_MainGrid.DataContext = m_Config;

            x_FrameRateCombo.ItemsSource = FrameRates.All;
        }

        private void x_OpenButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            if (ofd.ShowDialog().GetValueOrDefault())
            {
                x_FilenameTextBox.Text = ofd.FileName;
                m_Config.Basic.InputFile = ofd.FileName;
            }
        }

        private void x_EncodeButton_Click(object sender, RoutedEventArgs e)
        {
            if (!File.Exists(x_FilenameTextBox.Text)) return;

            x_EncodeButton.IsEnabled = false;
            x_OptionsPanel.IsEnabled = false;
            x_InPanel.IsEnabled = false;
            x_OutPanel.IsEnabled = false;
            x_CancelButton.IsEnabled = true;

            Thread encodeThread = new Thread(new ParameterizedThreadStart(EncoderThread));
            encodeThread.SetApartmentState(ApartmentState.STA);
            encodeThread.Start(m_Config);
        }

        void encoder_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Dispatcher.Invoke((System.Action)(() => { x_EncodeProgress.Value = e.ProgressPercentage; }), null);
        }

        private void EncoderThread(object args)
        {
            EncoderConfiguration config = args as EncoderConfiguration;

            Stopwatch sw = new Stopwatch();
            sw.Start();

            MediaSource ms = new MediaSource()
            {
                FileName = config.Basic.InputFile,
                MarkIn = TimeSpan.Zero,
                MarkOut = TimeSpan.Zero,
                FrameRate = 29.97,
                IncludeAudio = !String.IsNullOrEmpty(config.Audio.AudioProfile),
                IsInterlaced = false,
            };
            string avsfile = AvisynthScriptGenerator.Generate(new List<MediaSource>() { ms });

            using (VC1Encoder encoder = EncoderManager.CreateEncoder(m_Config))
            {
                m_Encoder = encoder;
                encoder.ProgressChanged += new EventHandler<ProgressChangedEventArgs>(encoder_ProgressChanged);

                //encoder.Config.BitRate = 1100;
                //encoder.Config.ComplexityLevel = 2;
                //encoder.Config.FrameRate = FrameRates.NTSCp;
                //encoder.Config.InterlacedSource = false;
                //encoder.Config.MaxKeyFrameDistance = 30;
                //encoder.Config.NumOfBFrames = 1;
                //encoder.Config.Profile = 2;
                //encoder.Config.QP = 31;
                //encoder.Config.RateControlMode = 0;
                //encoder.Config.VBVBufferInBytes = 1000 * 3 * 125;

                //encoder.Config.MaxWidth = 720;
                //encoder.Config.MaxHeight = 480;

                //encoder.MotionEstimation.DeltaMVRangeIndex = 3;
                //encoder.MotionEstimation.MotionSearchLevel = 4;
                //encoder.MotionEstimation.MotionSearchMethod = 2;
                //encoder.MotionEstimation.MBModeCost = 1;
                //encoder.MotionEstimation.MVRange = 4;

                encoder.Initialize(avsfile);

                EncoderManager.SetAdvancedSettings(encoder, m_Config);

                encoder.VideoType = 0;
                encoder.LookAhead = true;

                //encoder.VideoType = 2;
                encoder.Encode(config.Basic.OutputFile, config.Audio.AudioProfile);
            }
            m_Encoder = null;

            sw.Stop();
            Debug.WriteLine("Encode took " + sw.Elapsed);

            EncodingComplete();
        }

        private void EncodingComplete()
        {
            Dispatcher.Invoke((System.Action)(() => { 
                x_EncodeProgress.Value = 0;
                x_EncodeButton.IsEnabled = true;
                x_OptionsPanel.IsEnabled = true;
                x_InPanel.IsEnabled = true;
                x_OutPanel.IsEnabled = true;
                x_CancelButton.IsEnabled = false;
            }), null);
        }

        private void x_OutOpenButton_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog ofd = new SaveFileDialog();
            if (ofd.ShowDialog().GetValueOrDefault())
            {
                x_OutFilenameTextBox.Text = ofd.FileName;
                m_Config.Basic.OutputFile = ofd.FileName;
            }
        }

        private void x_ProfileBrowseButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Profiles (.prx)|*.prx";
            if (ofd.ShowDialog().GetValueOrDefault())
            {
                m_Config.Audio.AudioProfile = ofd.FileName;
            }
        }

        private void LoadSettings(string filename)
        {
            EncoderConfiguration config = EncoderConfiguration.Load(filename);
            if (config != null)
            {
                m_Config = config;
                x_MainGrid.DataContext = m_Config;
                if (!String.IsNullOrEmpty(m_Config.Audio.AudioProfile) && m_Config.Audio.AudioProfile != "default")
                {
                    x_ProfileAudioRadio.IsChecked = true;
                }
            }
        }

        private void SaveSettings(string filename)
        {
            XmlSerializer xmlSer = new XmlSerializer(typeof(EncoderConfiguration));
            using (StreamWriter sw = new StreamWriter(filename))
            {
                xmlSer.Serialize(sw, m_Config);
            }
        }

        private void x_CancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (m_Encoder != null)
            {
                m_Encoder.Cancel();
            }
        }

        private void x_SaveButton_Click(object sender, RoutedEventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "XML settings file (*.xml)|*.xml";
            sfd.AddExtension = true;
            if (sfd.ShowDialog().GetValueOrDefault())
            {
                m_Config.Save(sfd.FileName);
            }
        }

        private void x_LoadButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "XML settings file (*.xml)|*.xml";
            if (ofd.ShowDialog().GetValueOrDefault())
            {
                LoadSettings(ofd.FileName);
            }
        }
    }
}
